/**
 * logger.js - 日志工具模块
 * 
 * 这个模块使用Winston库创建一个可配置的日志记录器，支持多种日志级别和输出格式。
 * 它可以将日志输出到控制台和文件，便于开发和生产环境中的调试和监控。
 */

const { createLogger, format, transports } = require('winston');
const path = require('path');
const fs = require('fs');

// 确保日志目录存在
const logDir = 'logs';
if (!fs.existsSync(logDir)) {
  fs.mkdirSync(logDir);
}

// 定义日志格式
const logFormat = format.combine(
  format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
  format.errors({ stack: true }),
  format.splat(),
  format.json()
);

// 创建控制台输出格式
const consoleFormat = format.combine(
  format.colorize(),
  format.printf(({ timestamp, level, message, ...meta }) => {
    return `${timestamp} [${level}]: ${message} ${Object.keys(meta).length ? JSON.stringify(meta, null, 2) : ''}`;
  })
);

/**
 * 创建Winston日志记录器实例
 * 
 * 配置了两种传输方式：
 * 1. 控制台输出 - 用于开发环境中的即时反馈
 * 2. 文件输出 - 将日志保存到文件中，便于后续分析
 */
const logger = createLogger({
  level: process.env.LOG_LEVEL || 'info', // 从环境变量获取日志级别，默认为'info'
  format: logFormat,
  defaultMeta: { service: 'api-service' }, // 为所有日志条目添加服务名称
  transports: [
    // 控制台输出
    new transports.Console({
      format: consoleFormat,
    }),
    // 错误日志文件
    new transports.File({ 
      filename: path.join(logDir, 'error.log'), 
      level: 'error',
      maxsize: 5242880, // 5MB
      maxFiles: 5,
    }),
    // 组合日志文件
    new transports.File({ 
      filename: path.join(logDir, 'combined.log'),
      maxsize: 5242880, // 5MB
      maxFiles: 5,
    }),
  ],
  // 异常处理
  exceptionHandlers: [
    new transports.File({ filename: path.join(logDir, 'exceptions.log') }),
    new transports.Console({
      format: consoleFormat,
    }),
  ],
  // 退出时不退出进程
  exitOnError: false,
});

// 如果不是生产环境，则添加更详细的日志格式
if (process.env.NODE_ENV !== 'production') {
  logger.add(new transports.Console({
    format: format.combine(
      format.colorize(),
      format.simple()
    ),
  }));
}

/**
 * 创建一个简单的HTTP请求日志中间件
 * 
 * @param {Object} req - Express请求对象
 * @param {Object} res - Express响应对象
 * @param {Function} next - 下一个中间件函数
 */
logger.logRequest = (req, res, next) => {
  logger.info(`${req.method} ${req.originalUrl}`, {
    ip: req.ip,
    userAgent: req.get('User-Agent'),
  });
  next();
};

module.exports = logger;